# == Schema Information
# Schema version: 11
#
# Table name: bundles
#
#  id         :integer(11)     not null, primary key
#  user_id    :integer(11)     
#  title      :string(255)     
#  notes      :string(1024)    
#  created_at :datetime        
#  updated_at :datetime        
#  share_key  :string(255)     
#

class Bundle < ActiveRecord::Base
  include ActionView::Helpers::TextHelper
  
  #Associations
  belongs_to :user
  has_many :bundlings, :order => "current DESC", :dependent => :delete_all
  has_many :current_bundlings, :class_name => "Bundling", :include => :posting, :conditions => {'bundlings.current' => true}
  
  has_many :postings, :through => :bundlings, :order => "bundlings.current DESC"
  has_many :current_postings, :through => :current_bundlings, :source => :posting
  
  validates_presence_of :user_id
  validates_presence_of :title
  
  class << self
    # Copies a shared bundle to the current user's portfolio
    def create_from_shared(bundle, user)
      new_bundle = Bundle.new(:title => bundle.title, :notes => bundle.notes, :user => user)
      transaction do
        bundle.save!
        bundle.posting_ids.each do |posting_id|
          new_bundle.bundlings.create!(:user_id => current_user.id, :posting_id => posting_id)
        end
      end
      new_bundle
    end
  end
  
  # Overwrite the notes field to return a pretty printed version
  def notes
    textilize_without_paragraph(read_attribute(:notes))
  end
  
  # Generate an opaque key for a bundle so that adjacent shared bundle addresses are not guessable
  def share_key
    if read_attribute(:share_key).blank?
      self.update_attribute :share_key, Digest::SHA1.hexdigest("--#{id}--#{user_id}--")
    end
    read_attribute(:share_key)
  end

  # These are the attributes we currently use in the summary table on bundle view pages
  # It is possible to expand these to calculate averages for any other numeric attributes
  @@fields = [:amount_requested, :percent_funded, :borrower_apr, :debt_to_income_ratio, :bid_count].freeze

  # Calculate statistics for this Bundle
  def aggregates(recalculate=false)
    return @aggregates if !recalculate && @aggregates
    
    labeled_vectors = current_postings.inject(Hash.new { |h, k| h[k] = [] }) do |vector, posting|
      @@fields.each { |field| vector[field] << posting.send(field) if posting.send(field) }
      vector[:credit_score] << Posting::CREDIT_SCORES[posting.credit_grade] if Posting::CREDIT_SCORES[posting.credit_grade]
      vector
    end
    
    results = labeled_vectors.inject(Hash.new { |h, k| h[k] = 0.0 }) do |memo, vector|
      label, values = vector.first, vector.last
      memo[label] = values.inject(0.0) { |sum, val| sum += val } / values.length
      memo
    end
    results[:credit_score] = results[:credit_score].round
    results[:bid_count] = results[:bid_count].round
    @aggregates = results
  end
end
